{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Phystech@DataScience\n",
"## Домашнее задание 3\n",
"\n",
"**Правила, прочитайте внимательно:**\n",
"\n",
"* Выполненную работу нужно отправить телеграм-боту `@thetahat_ds25_bot`. Для начала работы с ботом каждый раз отправляйте `/start`. Дождитесь подтверждения от бота, что он принял файл. Если подтверждения нет, то что-то не так. **Работы, присланные иным способом, не принимаются.**\n",
"* Дедлайн см. в боте. После дедлайна работы не принимаются кроме случаев наличия уважительной причины.\n",
"* Прислать нужно **ноутбук в формате `ipynb`**. Если вы строите интерактивные графики, их стоит прислать в формате html.\n",
"* Следите за размером файлов. **Бот не может принимать файлы весом более 20 Мб.** Если файл получается больше, заранее разделите его на несколько.\n",
"* Выполнять задание необходимо полностью самостоятельно. **При обнаружении списывания всем участникам списывания дается штраф -2 балла к итоговой оценке за семестр.**\n",
"* Решения, размещенные на каких-либо интернет-ресурсах, не принимаются. Кроме того, публикация решения в открытом доступе может быть приравнена к предоставлении возможности списать.\n",
"* Обратите внимание на правила использования ИИ-инструментов при решении домашнего задания.\n",
"* **Код из рассказанных на занятиях ноутбуков** можно использовать без ограничений.\n",
"* Для выполнения задания используйте этот ноутбук в качестве основы, ничего не удаляя из него. Можно добавлять необходимое количество ячеек.\n",
"* Комментарии к решению пишите в markdown-ячейках.\n",
"* Выполнение задания (ход решения, выводы и пр.) должно быть осуществлено на русском языке.\n",
"* Решение проверяется системой ИИ-проверки
**ThetaGrader**. Результат проверки валидируется и исправляется человеком, после чего комментарии отправляются студентам.\n",
"* Если код будет не понятен проверяющему, оценка может быть снижена.\n",
"* Никакой код из данного задания при проверке запускаться не будет. *Если код студента не выполнен, недописан и т.д., то он не оценивается.*\n",
"\n",
"Важно!!! Правила заполнения ноутбука:\n",
"* Запрещается удалять имеющиеся в ноутбуке ячейки, менять местами положения задач.\n",
"* Сохраняйте естественный линейный порядок повествования в ноутбуке сверху-вниз.\n",
"* Отвечайте на вопросы, а также добавляйте новые ячейки в предложенных местах, которые обозначены `<...>`.\n",
"* В markdown-ячейка, содержащих описание задачи, находятся специальные отметки, которые запрещается модифицировать.\n",
"* При нарушении данных правил работа может получить 0 баллов.\n",
"\n",
"\n",
"**Перед выполнением задания посмотрите презентацию по выполнению и оформлению домашних заданий с занятия 2.**\n",
"\n",
"\n",
"**Баллы за задание:**\n",
"\n",
"\n",
"* Задача 1 — 40 баллов\n",
"* Задача 2 — 70 баллов\n",
"* Задача 3 — 20 баллов\n",
"\n",
"-----"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Bot check\n",
"\n",
"# HW_ID: phds_hw3\n",
"# Бот проверит этот ID и предупредит, если случайно сдать что-то не то\n",
"\n",
"# Status: not final\n",
"# Перед отправкой в финальном решении удали \"not\" в строчке выше\n",
"# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.model_selection import train_test_split, GroupShuffleSplit\n",
"from sklearn.preprocessing import StandardScaler\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.metrics import accuracy_score, balanced_accuracy_score\n",
"\n",
"from typing import List, Callable, Tuple\n",
"\n",
"import seaborn as sns\n",
"sns.set_theme('notebook', font_scale=1.2, palette='Set2')\n",
"\n",
"from tqdm.notebook import tqdm"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Задача 1\n",
"\n",
"Рассмотрим модель логистической регрессии. Признаки объекта представимы в виде $d$-мерного вектора $x \\in \\mathbb{R}^d$, класс имеет бернулиевское распределение $Y \\sim Bern(\\mu_\\theta(x))$. Мы делаем следующее предположение о зависимости параметра вероятности от признаков:\n",
"$${\\mu_\\theta(x) = \\sigma(x^T\\theta)= \\cfrac{1}{1 + e^{-x^T\\theta}}}.$$\n",
"\n",
"При добавлении регуляризации к модели логистической регрессии оптимизируемый функционал принимает вид\n",
"\n",
"$$\n",
" F(\\theta) = -\\sum_{i=1}^n \\left[Y_i \\log{\\sigma(\\theta^T x_i)} + (1 - Y_i) \\log{\\left(1 - \\sigma(\\theta^T x_i)\\right)}\\right] + \\lambda\\theta^T \\theta\n",
"$$\n",
"\n",
"1. Выпишите формулы градиентного спуска (GD) и стохастического градиентного спуска (SGD).\n",
"\n",
"2. Покажите, что $F(\\theta)$ — выпуклая функция по $\\theta$ и, как следствие, имеет единственный экстремум, являющийся глобальным максимумом. *Указание*. Посчитайте гессиан (матрицу вторых производных) и покажите, что она положительно определена.\n",
"\n",
"3. Опишите, как может вести себя решение при отсутствии регуляризации, то есть при $\\lambda = 0$"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CU79yNBgUkD3"
},
"source": [
"## Задача 2"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "j9egrAx6ohr5"
},
"source": [
"### Введение\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MNEtDc0IgeKf"
},
"source": [
"**РНК-интерференция** (англ. RNA interference; RNAi) — это естественный биологический процесс и перспективный с медицинской точки зрения метод подавления экспрессии генов в эукариотических клетках. Его применяют для изучения функций генов, [разработки новых лекарств](https://www.biopreparations.ru/jour/article/view/575?utm_source=chatgpt.com), а также при генной терапии.\n",
"\n",
"Механизм РНК-интерференции работает так: поступившая в клетку экзогенная двухцепочечная РНК связывается с рибонуклеазой Dicer, которая нарезает ее на ***малые интерферирующие РНК,*** **или миРНК** **(small interfering RNA, siRNA)** — *небольшие фрагменты длиной 20–25 пар нуклеотидов*. Эти фрагменты взаимодействуют с комплексом RISC, который использует siRNA как «наводку» для поиска нужной молекулы мРНК и расщепляет её, подавляя работу гена.\n",
"\n",
"> 📌 *Примечание.* В русскоязычной литературе аббревиатурой \"миРНК\" обозначают как siRNA, так и miRNA (микро-РНК), что нередко приводит к путанице. Условимся, под миРНК мы будем иметь в виду именно *малые интерферирующие РНК (siRNA)*."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gbmEqR0pYLgL"
},
"source": [
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wcCk-SMWgWrp"
},
"source": [
"*Проблема* заключается в том, что не все миРНК одинаково эффективны в подавлении экспрессии генов. Способность миРНК к ингибированию измеряется с помощью количественной ОТ-ПЦР, *однако* существуют гипотезы, что определенные характеристики олигонуклеотидов могут предсказать их эффективность.\n",
"\n",
"**Описание датасета**\n",
"\n",
"[Датасет](https://www.kaggle.com/datasets/livtoft/sirna-activity/data) содержит 653 олигонуклеотида, информацию о целевой мРНК, последовательности миРНК, а также характеристики, которые могут быть предикторами активности миРНК.\n",
"\n",
"* `target mRNA` — идентификатор целевой мРНК.\n",
"\n",
"* `Start / End` — начальная и конечная позиции миРНК на целевой мРНК.\n",
"\n",
"* `Sequence` — последовательность нуклеотидов в миРНК.\n",
"\n",
"* `G / U` — количество нуклеотидов гуанина (G) и урацила (U) в миРНК.\n",
"\n",
"* `bi` — стабильность димеров антисмысловой цепи (энергия связи между одинаковыми цепями).\n",
"\n",
"* `uni` — внутримолекулярная стабильность антисмысловой цепи (способность цепи формировать петли или шпильки).\n",
"\n",
"* `duplex` — энергия связи между антисмысловой и смысловой цепями миРНК (чем меньше, тем прочнее комплекс).\n",
"\n",
"* `Pos1,2,6,13,14,18` — стабильность связи пар оснований в ключевых позициях siRNA при взаимодействии с мРНК.\n",
"* `Dif_5-3` — разница стабильности концов миРНК (5' и 3').\n",
"\n",
"* `Content+ / Content-` — содержание нуклеотидов на положительной и отрицательной цепи.\n",
"\n",
"* `Cons+ / Cons- / Cons_Sum` — консервативность последовательностей (на положительной, отрицательной цепи и суммарно).\n",
"\n",
"* `Hyb19` — энергия гибридизации с мРНК (длина 19 пар оснований).\n",
"\n",
"* `target` — цель (идентификатор).\n",
"\n",
"* `Activity` — процент остаточной экспрессии целевой мРНК. **Чем меньше активность, тем выше эффективность подавления экспрессии гена.**\n",
"\n",
"Согласно [оригинальной статье](https://bmcbioinformatics.biomedcentral.com/articles/10.1186/1471-2105-7-65#Tab1), эти признаки должны помочь выявлять миРНК, наиболее эффективно подавляющие экспрессию гена."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ToHJKlibWHh8"
},
"source": [
"### 1. Загрузка и подготовка данных\n",
"Загрузите датасет и выведите первые несколько строк."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 273
},
"executionInfo": {
"elapsed": 366,
"status": "ok",
"timestamp": 1741429452777,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "LftkTnn26XPn",
"outputId": "23f5951d-e4dd-4760-d9b6-db07fd889cbf"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "skf-j3eCWw0m"
},
"source": [
"Проверьте, есть ли в данных пропуски? Все ли столбцы имеют числовой формат?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 51,
"status": "ok",
"timestamp": 1741429459208,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "ZxjaVrHhXItG",
"outputId": "f2d9e501-f985-4da5-df9e-2aeb2d20a40c"
},
"outputs": [],
"source": [
"data.info()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QsJJoP2aDMAF"
},
"source": [
"**Ответ:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CsyizeWbmZCC"
},
"source": [
"Отличается ли масштаб у числовых признаков?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 349
},
"executionInfo": {
"elapsed": 103,
"status": "ok",
"timestamp": 1741429461644,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "9venGWOXzm6L",
"outputId": "68343753-836c-4bae-d446-9952660645eb"
},
"outputs": [],
"source": [
"data.describe()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "F43_EvWADZan"
},
"source": [
"**Ответ:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EGtRO0vti2QC"
},
"source": [
"Посмотрим на распределение активности:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 349
},
"executionInfo": {
"elapsed": 350,
"status": "ok",
"timestamp": 1741429463430,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "UpU1rAGgify_",
"outputId": "70eeb49e-5b03-4497-8192-8f64190a7415"
},
"outputs": [],
"source": [
"plt.figure(figsize=(10, 4))\n",
"sns.histplot(data['Activity']);"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "peNhuuKhwhXO"
},
"source": [
"Удивление могут вызывать значения активности свыше 100%. Как будто бы в некоторых случаях последовательность миРНК вместо подавления, напротив, усиливала экспрессию мРНК. Эта тайна, покрытая мраком, остаётся на совести экспериментаторов 🤔. Более важно научиться предсказывать эффективные последовательности, при применении которых остаточная активность мала. В качестве порогового значения возьмём 30% и будем пытаться отделять (классифицировать) эффективные и неэффективные цепочки миРНК по такому правилу:\n",
"\n",
"* 1 (эффективная): миРНК снижает уровень мРНК более чем на 70% (значение активности ≤ 30%).\n",
"\n",
"* 0 (неэффективная): миРНК снижает уровень мРНК менее чем на 30% (значение активности > 30%)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oO7v_X8apVMq"
},
"source": [
"Установите порог, выделите матрицу признаков и целевую переменную:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 14,
"status": "ok",
"timestamp": 1741429464925,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "bWozemt4TFi6",
"outputId": "587858a6-179f-423d-d6f4-c7dac74a4601"
},
"outputs": [
{
"data": {
"text/plain": [
"((653, 21), (653,))"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"<...>\n",
"\n",
"X.shape, y.shape"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZCSNIMNVqQIP"
},
"source": [
"Посчитайте количество нулей и единиц таргете. Лучше всего представить ответ в виде графика с двумя столбцами, высота которых соответствует количеству объектов класса (см. например, [`sns.countplot`](https://seaborn.pydata.org/generated/seaborn.countplot.html)). Есть ли дисбаланс между классами?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 347
},
"executionInfo": {
"elapsed": 310,
"status": "ok",
"timestamp": 1741429465847,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "4XfauL47qxuw",
"outputId": "52a3897e-e663-4dd8-c6fe-5c1074557932"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "LuyULxleqs8j"
},
"source": [
"**Ответ:** "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WotkphbSbZ8x"
},
"source": [
"Хорошо ли обусловлена матрица $X$? О чём это говорит?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 4,
"status": "ok",
"timestamp": 1741429471233,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "e2zUTvvNboAu",
"outputId": "090d7e5f-4e81-4031-86bc-51d978a9bc95"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "R-OP8rFzbot0"
},
"source": [
"**Ответ:** "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9O5_ivgrboWQ"
},
"source": [
"Для наглядности, выведите матрицу корреляций. Что означают элементы матрицы? А в нашем случае?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 553
},
"executionInfo": {
"elapsed": 594,
"status": "ok",
"timestamp": 1741429473531,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "6NhLM16xUEeL",
"outputId": "f034cecb-e9aa-412b-b6e2-2aa5f38102cb"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "_xv-p6EmcpTw"
},
"source": [
"**Ответ:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZSdn_bI3eK0z"
},
"source": [
"Разделите данные на обучающую и тестовую выборки в отношении 3:2. Вам не подойдет стандартный метод `test_train_split`, так как в данных есть группы (столбец `Target seq`): для каждой целевой последовательности подбирались различные цепочки миРНК:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 305
},
"executionInfo": {
"elapsed": 940,
"status": "ok",
"timestamp": 1741429478727,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "OF0qkFnp3W4d",
"outputId": "22e5f9a8-f031-4443-cb57-6b475a2005a7"
},
"outputs": [],
"source": [
"plt.figure(figsize=(15, 4))\n",
"sns.countplot(x=data['Target seq'])\n",
"plt.xticks(rotation=90, fontsize=11)\n",
"plt.title('Количество записей в данных по всем последовательностям (группам)');"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "euAwu9Dl3VaX"
},
"source": [
"Реализуйте разделение на тренировочную и тестовую выборки так, чтобы все группы попали целиком только в одну из частей. Вы можете реализовать алгоритм самостоятельно или воспользоваться готовыми решениями, например [`GroupShuffleSplit`](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GroupShuffleSplit.html), используя метод `groups`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"executionInfo": {
"elapsed": 1,
"status": "ok",
"timestamp": 1741429478835,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "S1NnEVtaUQxd"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "pZ4RVBKs8fHk"
},
"source": [
"Выведите что-либо, подтверждающее корректность вашего разбиения. Чем плохо, если элементы выборки, соответствующие одной и той же целевой последовательности, попадут одновременно в тестовую и обучающую выборку?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 8,
"status": "ok",
"timestamp": 1741429480004,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "5lmn2MmE8pAc",
"outputId": "93fd3522-82b8-4f0e-8c8c-caa908ea0e20"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "01lGEB-VkoHT"
},
"source": [
"**Ответ:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "FasnwnTTfurM"
},
"source": [
"Выведите распределение данных по классам для обеих выборок, аналогично тому, как вы делали в начале для всей выборки. Одинаково ли распределение на обучающей и тестовой выборках?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 393
},
"executionInfo": {
"elapsed": 315,
"status": "ok",
"timestamp": 1741429481697,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "-B80aN8Sf_Zi",
"outputId": "351d9cfc-320f-4dae-8966-28b4634d64c2"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "VGWHpYiLlKm1"
},
"source": [
"**Ответ:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "u1rQPD-B4ChX"
},
"source": [
"Далее, при построении классификатора, учитывайте диcбаланс, если он есть: используйте взвешенную версию логистической регрессии (см. параметр `class_weight`) и метрику [`balanced_accuracy_score`](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html#sklearn.metrics.balanced_accuracy_score) для оценки качества модели. **❗Это очень важно❗**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "i92T7Tzjlr_M"
},
"source": [
"Стандартизируйте данные."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"executionInfo": {
"elapsed": 15,
"status": "ok",
"timestamp": 1741429694304,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "YPfLY6PFft-T"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "2HETnbQImfLX"
},
"source": [
"### 2. Модельки, модельки, модельки..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oDQsDGXBoPlT"
},
"source": [
"#### 2.1 Самый популярный класс\n",
"\n",
"Найдите самый популярный класс в обучающей выборке и посчитайте точность ответа на трейне и тесте только этим классом — константой. Отличается ли взвешенная точность от обычной?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 67,
"status": "ok",
"timestamp": 1741429698258,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "XedCeRCwmCOV",
"outputId": "e03959dc-5060-4e5f-c2a7-abb9c4872ab5"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Взвешенная точность на тесте: 0.500, на трейне: 0.500\n",
"Обычная точность на тесте: 0.525, на трейне: 0.563\n"
]
}
],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "9SNWMYEFsBSZ"
},
"source": [
"**Вывод:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "onpsFqPAsXVy"
},
"source": [
"#### 2.2 Логистическая регрессия без регуляризации\n",
"\n",
"Обучите классическую логистическую регрессию без регуляризации и визуализируйте точность ответа на трейне и тесте. **Свободный коэффициент необходимо исключить из модели**.\n",
"\n",
"\n",
" Подсказка ✍️
\n",
" \n",
"> Чему равен аргумент `penalty` по умолчанию?\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 43,
"status": "ok",
"timestamp": 1741429699861,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "1w20K0fvqLXd",
"outputId": "d3b0b0fc-4d62-42ec-d604-09afdbd429ba"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "nyP9H6duuDde"
},
"source": [
"**Вывод:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dEWczwxTRuky"
},
"source": [
"#### 2.3 Логистическая регрессия с регуляризацией"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "KrnG7dX3Rucu"
},
"source": [
"За что отвечает гиперпараметр `C` у класса `LogisticRegression`?"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "KOkRAHLrR6ag"
},
"source": [
"**Ответ:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "s_p3T2OUuL1T"
},
"source": [
"Вам необходимо исследовать зависимость от `C` следующих величин:\n",
"1. Accuracy на трейне\n",
"2. Accuracy на тесте\n",
"3. Коэффициенты модели\n",
"\n",
"Чтобы не приходилось постоянно обучать модели при одних и тех же сетках `C`, предлагается написать функцию, которая будет принимать на вход вид штрафа `penalty`, границы диапазона `C`, и саму выборку. На каждой итерации вычисляйте все величины и сохраняйте в виде списков. Для мониторинга времени работы используйте функцию `tqdm`. Пример использования:\n",
"\n",
"```\n",
"from tqdm.notebook import tqdm\n",
"for C in tqdm(C_grid):\n",
" <тело цикла>\n",
"```\n",
"\n",
"Не забудьте также про имеющийся дисбаланс классов."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"executionInfo": {
"elapsed": 8,
"status": "ok",
"timestamp": 1741429706146,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "9lp9hyMptJvu"
},
"outputs": [],
"source": [
"def train_alpha_grid(\n",
" min_log_C: float,\n",
" max_log_C: float,\n",
" resolution: int,\n",
" X_train: pd.DataFrame,\n",
" y_train: np.ndarray,\n",
" X_test: pd.DataFrame,\n",
" y_test: np.ndarray,\n",
" penalty: str,\n",
" solver: str = 'newton-cholesky',\n",
" max_iter: int = 100\n",
") -> Tuple[np.ndarray, List[List[float]], List[float], List[float]]:\n",
" \"\"\"Обучает модель LogisticRegression для разных значений параметра регуляризации C,\n",
" сохраняет коэффициенты, вычисляет accuracy на обучающей и тестовой выборках.\n",
"\n",
" Args:\n",
" min_log_C (float): минимальное значение log10(C) для сетки.\n",
" max_log_C (float): максимальное значение log10(C) для сетки.\n",
" resolution (int): число точек на сетке C.\n",
" X_train (pd.DataFrame): обучающая выборка (признаки).\n",
" y_train (np.ndarray): отклик на обучающей выборке.\n",
" X_test (pd.DataFrame): тестовая выборка (признаки).\n",
" y_test (np.ndarray): отклик на тестовой выборке.\n",
" penalty (str): тип регуляризации ('l1', 'l2', 'elasticnet', 'none').\n",
" solver (str, optional): метод оптимизации параметров модели. По-умолчанию 'newton-cholesky'.\n",
" max_iter (int, optional): максимальное количество итераций для оптимизации. По-умолчанию 100.\n",
"\n",
" Returns:\n",
" Tuple[np.ndarray, List[List[float]], List[float], List[float]]:\n",
" - C_grid (np.ndarray): сетка значений C,\n",
" - coefs_list (List[List[float]]): список коэффициентов для каждого значения C,\n",
" - baccuracy_train_list (List[float]): список balanced accuracy на обучающей выборке для каждого значения C,\n",
" - baccuracy_test_list (List[float]): список balanced accuracy на тестовой выборке для каждого значения C.\n",
" \"\"\"\n",
"\n",
" <...>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UAoXOQifNJan"
},
"source": [
"Проведите эксперимент для 3-х разных моделей логистической регрессии с различными типами регуляризации:\n",
"1. $L_1$-регуляризация\n",
"2. $L_2$-регуляризация\n",
"3. Комбинированная регуляризация с параметром `l1_ratio=0.5`.\n",
"\n",
">*Рекомендации*\n",
">* Подберите диапазоны значений для гиперпараметра `C`. Не берите слишком узкие, чтобы видеть на графике всю картину. Для слишком широких границ придётся брать больше точек.\n",
">* Вам не нужна очень частая сетка гиперпараметра `C`. При отладке кода можно вообще использовать сетку из 2-3 значений.\n",
">* Вы можете столкнуться с различными ошибками и `warning`-ами (например, неверный `solver`, отсутствие сходимости, и т.д.) Постарайтесь настроить гиперпараметры модели таким образом, чтобы ошибки исчезли, а количество предупреждений было минимальным.\n",
">* Для ускорения работы программы можно использовать параллельные вычисления, передав аргумент `n_jobs` в модель. Это особенно полезно при запуске на локальном компьютере, так как Google Colab предоставляет лишь два ядра ЦПУ по-умолчанию."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "DQ6eN1k1RUqm"
},
"source": [
"Нарисуйте треки коэффициентов моделей в зависимости от `C`. Легенду можно сделать общую, если все графики помещаются на экране. Отразите в ней наименования признаков для соответствующих коэффициентов. Сделать красиво могут помочь заметки [отсюда](https://stackoverflow.com/questions/4700614/how-to-put-the-legend-outside-the-plot)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 418
},
"executionInfo": {
"elapsed": 1097,
"status": "ok",
"timestamp": 1741429949283,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "BbW63vbvDI0m",
"outputId": "1ed2242f-4b90-488a-8221-e8d72a32a1eb"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "bYpm-quhZoW7"
},
"source": [
"**Вывод:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "316NMxZZZrcO"
},
"source": [
"Нарисуйте зависимости точности предсказания от `C` на обучающей и тестовой выборках. Скомпонуйте всё на 2-3 графиках. Горизонтальными линиями, отметьте точность модели без регуляризации на трейне и тесте."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 261
},
"executionInfo": {
"elapsed": 802,
"status": "ok",
"timestamp": 1741429950092,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "YU449ztgFoFE",
"outputId": "6a25397b-13b3-4f49-cc9d-8d4727d67618"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "IA125gwxTrlj"
},
"source": [
"Сделайте общий вывод по задаче. Есть ли пользва от регуляризации с точки зрения метрики? Получается ли удовлетворить всем трём перечисленным условиям одновременно?"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "zdaFidTycI0A"
},
"source": [
"**Вывод:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EWlq9RI9ju0A"
},
"source": [
"## Задача 3 (продолжение)\n",
"Продолжайте работать с этим датасетом. Далее используйте $L_2$-регуляризацию."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2fNYSdZPFyJ9"
},
"source": [
"### 1. Число обусловленности\n",
"Исследуйте зависимость числа обусловленности от параметра `C`. Постройте соответствующий график."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 384
},
"executionInfo": {
"elapsed": 785,
"status": "ok",
"timestamp": 1741429951608,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "vjg6PHoTRKr4",
"outputId": "4524fd72-6ac1-4ded-edd1-0e226784023b"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "1PhVrxvgHAOs"
},
"source": [
"**Вывод:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pSznT1sEHEpg"
},
"source": [
"### 2. Предсказание вероятностей\n",
"\n",
"Исследуйте распределение предсказываемых вероятностей для логистической регерессии с регуляризацией и без.\n",
"\n",
"Для начала, реализуйте функцию, которая будет обучать логистическую регрессию с наиболее оптимальным `C` и возвращать предсказание вероятности для касса $0$. Для этого у всех классификаторов `sklearn` предусмотрен метод `predict_proba`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"executionInfo": {
"elapsed": 39,
"status": "ok",
"timestamp": 1741430066367,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "upbI1j6cUUry"
},
"outputs": [],
"source": [
"def get_proba_distr(\n",
" X_train: pd.DataFrame,\n",
" y_train: np.ndarray,\n",
" X_test: pd.DataFrame,\n",
" C: float = np.inf\n",
") -> Tuple[np.ndarray, float]:\n",
"\n",
" <...>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GImXdSTlUl2q"
},
"source": [
"Сравните гистограммы распределения предсказанных вероятностей для двух указанных моделей. Используйте логарифмический масштаб по вертикальной оси."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 646
},
"executionInfo": {
"elapsed": 1120,
"status": "ok",
"timestamp": 1741430345195,
"user": {
"displayName": "Артём Логинов",
"userId": "16122714672800212068"
},
"user_tz": -180
},
"id": "HYPxPRh9UlPJ",
"outputId": "0163a8b0-028d-48e8-d7a2-053ded71aba8"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "LFm8OFFcS6FJ"
},
"source": [
"**Вывод:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Ri40ptDpztRl"
},
"source": [
"**Интересные статьи:**\n",
"\n",
"[Червивый путь к Нобелю: история miRNA и больших открытий](https://nplus1.ru/material/2024/10/08/microrna-nobel2024)"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 0
}